package net.j4love.concurrency.practice.c1;

import net.j4love.concurrency.NotThreadSafe;
import org.junit.Test;

import java.util.concurrent.CountDownLatch;

/**
 * @author he peng
 * @create 2018/6/25 11:35
 * @see
 */
public class UnsafeSequenceTest {

    @NotThreadSafe
    class UnsafeSequence {
        private int value;

        public int next() {
            try {
                // 模拟放弃 cpu 执行权
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // ++ 不是一个原子操作
            return this.value++;
        }
    }


    class MyThread extends Thread {
        UnsafeSequence unsafeSequence;
        CountDownLatch countDownLatch;

        public MyThread(String name, UnsafeSequence unsafeSequence, CountDownLatch countDownLatch) {
            super(name);
            this.unsafeSequence = unsafeSequence;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            for (int i = 0 ; i < 20 ; i++) {
                System.out.println(Thread.currentThread().getName() + " , next = " + unsafeSequence.next());
            }
            countDownLatch.countDown();
        }
    }

    @Test
    public void test0() throws Exception {
        final CountDownLatch countDownLatch = new CountDownLatch(3);

        final UnsafeSequence unsafeSequence = new UnsafeSequence();
        new Thread("UnsafeSequenceTest-Thread-1") {
            @Override
            public void run() {
                for (int i = 0 ; i < 10 ; i++) {
                    System.out.println(Thread.currentThread().getName() + " , next = " + unsafeSequence.next());
                }
                countDownLatch.countDown();
            }
        }.start();

        new Thread("UnsafeSequenceTest-Thread-2") {
            @Override
            public void run() {
                for (int i = 0 ; i < 100 ; i++) {
                    System.out.println(Thread.currentThread().getName() + " , next = " + unsafeSequence.next());
                }
                countDownLatch.countDown();
            }
        }.start();

        new Thread("UnsafeSequenceTest-Thread-3") {
            @Override
            public void run() {
                for (int i = 0 ; i < 100 ; i++) {
                    System.out.println(Thread.currentThread().getName() + " , next = " + unsafeSequence.next());
                }
                countDownLatch.countDown();
            }
        }.start();

        countDownLatch.await();
    }

    @Test
    public void test1() throws Exception {
        CountDownLatch countDownLatch = new CountDownLatch(3);
        UnsafeSequence unsafeSequence = new UnsafeSequence();

        new MyThread("UnsafeSequenceTest-Thread-1" , unsafeSequence , countDownLatch).start();
        new MyThread("UnsafeSequenceTest-Thread-2" , unsafeSequence , countDownLatch).start();
        new MyThread("UnsafeSequenceTest-Thread-3" , unsafeSequence , countDownLatch).start();

        countDownLatch.await();

    }
}
